//
//  FIPTcpSocket.m
//  fireplace
//
//  Created by XiangDongMBP on 2017/3/17.
//  Copyright © 2017年 East. All rights reserved.
//

#import "FIPTcpSocket.h"
#import <GCDAsyncSocket.h>

@interface FIPTcpSocket ()<GCDAsyncSocketDelegate>
@property (nonatomic, strong) GCDAsyncSocket *socket;
@property (nonatomic, assign) Byte ssid;                //!< 当前连接的SSID
@property (nonatomic, assign) FIPRequestType reqType;   //!< 当前业务的请求type
@property (nonatomic, strong) NSData *dataByte;         //!< 业务提供的4字节数据体
@property (nonatomic, strong) NSData *conDataByte;      //!< 建立连接用的4字节数据体

@property (nonatomic, copy)   void(^successHandle)(NSData *data);   //!< 成功的Block
@property (nonatomic, copy)   void(^failureHandle)(NSError *error); //!< 失败的Block

@end

static NSString *const kServerHost = @"10.10.100.250";  //!< 服务器IP
static uint16_t  const kServerPort = 8899;              //!< 端口
static NSInteger const kConnectTimeout = 5;             //!< 连接超时时间
static NSInteger const kWriteDataTimeout = 5;           //!< 写数据超时时间
static NSInteger const kReadDataTimeout = 5;            //!< 读数据超时时间

@implementation FIPTcpSocket
- (instancetype)initWithDelegate:(id)delegate {
    self = [super init];
    if (self) {
        _delegate = delegate;
    }
    return self;
}

- (void)sendToServerWithReqType:(FIPRequestType)type dataByte:(NSData *)dataByte success:(void (^)(NSData * _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure {
    self.successHandle = success;
    self.failureHandle = failure;
    
    [self sendToServerWithReqType:type dataByte:dataByte];
}

- (void)sendToServerWithReqType:(FIPRequestType)type dataByte:(nonnull NSData *)dataByte {
    self.reqType = type;
    self.dataByte = dataByte;
    
    //每次先断开连接
    [self.socket setDelegate:nil];
    [self.socket disconnect];
    [self.socket setDelegate:self];
    
    // 连接服务器
    [self connectToServer];
}

- (void)connectToServer {
    // 连接服务器
    NSError *error;
    if (![self.socket connectToHost:kServerHost onPort:kServerPort withTimeout:kConnectTimeout error:&error]) {
        if ([self.delegate respondsToSelector:@selector(fIPTcpSocket:failedWithError:)]) {
            [self.delegate fIPTcpSocket:self failedWithError:error];
        }
        if (self.failureHandle) {
            self.failureHandle(error);
            self.failureHandle = nil;
        }
    } else {
        NSLog(@"开始连接");
    }
}

#pragma mark - GCDAsyncSocketDelegate
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"连接到主机:%@ %zd", host, port);
    // 连接成功，建立连接
    NSData *conData = [self getSevenDataWithReqType:FIPRequestTypeSync dataByte:self.conDataByte];
    [sock writeData:conData withTimeout:kWriteDataTimeout tag:0];
    
    // 发送之后，开始读取数据
    [sock readDataToLength:21 withTimeout:kReadDataTimeout tag:0];
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
    NSLog(@"断开连接:%@", err);
    if ([self.delegate respondsToSelector:@selector(fIPTcpSocket:failedWithError:)]) {
        [self.delegate fIPTcpSocket:self failedWithError:err];
    }
    if (self.failureHandle) {
        self.failureHandle(err);
        self.failureHandle = nil;
    }
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    NSLog(@"发送%@成功", self.dataByte);
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSLog(@"读取数据%@成功", data);
    if (self.reqType == FIPRequestTypeSync) {
        [self successWithData:data];
        [self disconnectSocket];
    } else {
        // 先判断是否是7字节，也就是已经返回(或者用tag来判断)
        // 是，直接返回
        //------------------------------------
        if (data.length == 7) {
            [self successWithData:data];
            [self disconnectSocket];
            return;
        }
        
        // 否，进行下一步
        // 提取SSID
        // 继续发送下一步指令
        // write...
        // read...
        if (data.length == 21) {
            Byte byte[2];
            [data getBytes:byte range:NSMakeRange(0, 2)];
            if (byte[0] == 0xA5) {
                self.ssid = byte[1];
            }else{
                NSLog(@"数据错误");
                self.ssid = byte[1];
            }
        }
        NSData *conData = [self getSevenDataWithReqType:self.reqType dataByte:self.dataByte];
        [sock writeData:conData withTimeout:kWriteDataTimeout tag:0];
        // 发送之后，开始读取数据
        [sock readDataToLength:7 withTimeout:kReadDataTimeout tag:0];
    }
}

#pragma mark - private methods
- (NSData *)getSevenDataWithReqType:(FIPRequestType)type dataByte:(NSData *)dataByte {
    if (dataByte.length != 4) {
        assert("dataByte length is not 4");
    }
    Byte byte[7] = {0xA5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
    byte[1] = (type == FIPRequestTypeSync) ? 0x00 : self.ssid;
    byte[2] = type;
    [dataByte getBytes:&byte[3] range:NSMakeRange(0, 4)];
    NSData *data = [NSData dataWithBytes:byte length:7];
    return data;
}

- (void)disconnectSocket {
    self.socket.delegate = nil;
    [self.socket disconnect];
}

- (void)failureWithError:(NSError *)error {
    ;
}
- (void)successWithData:(NSData *)data {
    if ([self.delegate respondsToSelector:@selector(fIPTcpSocket:successWithData:)]) {
        [self.delegate fIPTcpSocket:self successWithData:data];
    }
    if (self.successHandle) {
        self.successHandle(data);
        self.successHandle = nil;
    }
}

#pragma mark - getters and setters
- (GCDAsyncSocket *)socket {
    if (!_socket) {
        _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    return _socket;
}

- (NSData *)conDataByte {
    if (!_conDataByte) {
        Byte byte[4] = {0x01, 0x00, 0x00, 0x00};
        _conDataByte = [NSData dataWithBytes:byte length:4];
    }
    return _conDataByte;
}

@end
